#include "edge.h"
#include <iostream>

#include "vertex.h"
#include "face.h"

Edge::Edge(int _id, bool _b) : id(_id), inBoundary(_b){
    selected = false;

    start = NULL;
    end = NULL;
    clockwise = NULL;
    counterClockwise = NULL;
    nextClockwise = NULL;
    nextClockwiseSignal = true;
    previousClockwise = NULL;
    previousClockwiseSignal = true;
    nextCounterClockwise = NULL;
    nextCounterClockwiseSignal = true;
    previousCounterClockwise = NULL;
    previousCounterClockwiseSignal = true;
}

Edge::Edge(int _id, Vertex* _s, Vertex *_e, bool _b) : id(_id), inBoundary(_b), start(_s), end(_e){
    selected = false;
    clockwise = NULL;
    counterClockwise = NULL;
    nextClockwise = NULL;
    nextClockwiseSignal = true;
    previousClockwise = NULL;
    previousClockwiseSignal = true;
    nextCounterClockwise = NULL;
    nextCounterClockwiseSignal = true;
    previousCounterClockwise = NULL;
    previousCounterClockwiseSignal = true;
}

Edge::~Edge(){
}

int Edge::getID() const{
    return id;
}

void Edge::select(bool _s){
    selected = _s;
}

bool Edge::isSelected(){
    return selected;
}

void Edge::setIsBoundary(bool _b){
    inBoundary = _b;
}

bool Edge::isBoundary(){
    return inBoundary;
}

void Edge::setStart(Vertex *_v){
    start = _v;
}

Vertex *Edge::getStart(){
    return start;
}

void Edge::setEnd(Vertex *_v){
    end = _v;
}

Vertex *Edge::getEnd(){
    return end;
}

void Edge::setClockwise(Face *_f){
    clockwise = _f;
}

Face *Edge::getClockwise(){
    return clockwise;
}

void Edge::setCounterClockwise(Face *_f){
    counterClockwise = _f;
}

Face *Edge::getCounterClockwise(){
    return counterClockwise;
}

void Edge::setNextClockwise(Edge *_e, bool _es){
    nextClockwise = _e;
    nextClockwiseSignal = _es;
}

Edge *Edge::getNextClockwise(){
    return nextClockwise;
}

bool Edge::getNextClockwiseSignal(){
    return nextClockwiseSignal;
}

void Edge::setPreviousClockwise(Edge *_e, bool _es){
    previousClockwise = _e;
    previousClockwiseSignal = _es;
}

Edge *Edge::getPreviousClockwise(){
    return previousClockwise;
}

bool Edge::getPreviousClockwiseSignal(){
    return previousClockwiseSignal;
}

void Edge::setNextCounterClockwise(Edge *_e, bool _es){
    nextCounterClockwise = _e;
    nextCounterClockwiseSignal = _es;
}

Edge *Edge::getNextCounterClockwise(){
    return nextCounterClockwise;
}

bool Edge::getNextCounterClockwiseSignal(){
    return nextCounterClockwiseSignal;
}

void Edge::setPreviousCounterClockwise(Edge *_e, bool _es){
    previousCounterClockwise = _e;
    previousCounterClockwiseSignal = _es;
}

Edge *Edge::getPreviousCounterClockwise(){
    return previousCounterClockwise;
}

bool Edge::getPreviousCounterClockwiseSignal(){
    return previousCounterClockwiseSignal;
}

void Edge::print() const{
    char ncwSignal;
    if(!nextClockwiseSignal) ncwSignal = '-';
    else ncwSignal = '+';

    char pcwSignal;
    if(!previousClockwiseSignal) pcwSignal = '-';
    else pcwSignal = '+';

    char nccwSignal;
    if(!nextCounterClockwiseSignal) nccwSignal = '-';
    else nccwSignal = '+';

    char pccwSignal;
    if(!previousCounterClockwiseSignal) pccwSignal = '-';
    else pccwSignal = '+';

	std::cout << "E" << id << ";\t V" << start->getID() << ";\t V" << end->getID();
	if (clockwise) std::cout << ";\t F" << clockwise->getID();
    else std::cout << ";\t";
	if (counterClockwise) std::cout << ";\t F" << counterClockwise->getID();
    else std::cout << ";\t";
    if (clockwise) {
        std::cout << ";\t" << ncwSignal <<  "E" << nextClockwise->getID()
        << ";\t" << pcwSignal <<  "E" << previousClockwise->getID();
    }else{
        std::cout << ";\t;\t";
    }
    if (counterClockwise){
        std::cout << ";\t" << nccwSignal <<  "E" << nextCounterClockwise->getID()
        << ";\t" << pccwSignal <<  "E" << previousCounterClockwise->getID();
    }else{
        std::cout << ";\t;\t";
    }
	if(inBoundary) std::cout << ";\tÉ da borda!" <<std::endl;
    std::cout << std::endl;
}


bool isParallel(Edge _e1, Edge _e2){
    Point p1 = (_e1.getEnd()->getPoint() - _e1.getStart()->getPoint()).normalization();
    Point p2 = (_e2.getEnd()->getPoint() - _e2.getStart()->getPoint()).normalization();
    return isCollinear(p1, p2);
}

bool haveIntersection(Edge _e1, Edge _e2){
    Point a = _e1.getStart()->getPoint();
    Point b = _e1.getEnd()->getPoint();
    Point c = _e2.getStart()->getPoint();
    Point d = _e2.getEnd()->getPoint();

    return haveIntersection(a, b, c, d);
}

bool haveIntersection(Point _a, Point _b, Point _c, Point _d){
    Point ab = (_b - _a);
    Point cd = (_d - _c);

    if( ( ab.crossProduct(_c - _a).dotProduct(ab.crossProduct(_d - _a)) ) >= 0.0) return false;
    if( ( cd.crossProduct(_a - _c).dotProduct(cd.crossProduct(_b - _c)) ) >= 0.0) return false;

    return true;
}
